"""
Created on 26-Jan-2010

@author: dexen
"""
import sys
import time
import threading as th
import Queue as qu

from dexen.system.base.task import InputUnit, OutputUnit
from dexen.system.base.exceptions import ScriptException, SlaveException

RUNNING = 1
STOPPED = 2
PAUSED = 3

IDLE = 0
PROCESSING = 1
SCRIPT_CRASHED = 2
SLAVE_CRASHED = 3

class SlaveComm(object):
    def __init__(self, slave_name, slavedir):
        self.inq = qu.Queue()
        self.outq = qu.Queue()
        self.slave_name = slave_name
        self._state = IDLE
        sys.path.append(slavedir)
        self._rank = 0
        self.lock = th.RLock()
        self._exc = None
    
    def reset(self):
        with self.lock:
            self.inq = qu.Queue()
            self.out = qu.Queue()
    
    def crash(self, state, msg):
        assert state == SLAVE_CRASHED or state == SCRIPT_CRASHED
        with self.lock:
            self._state = state
            if state == SLAVE_CRASHED:
                self._exc = SlaveException(msg) 
            if state == SCRIPT_CRASHED:
                self._exc = ScriptException(msg) 
            self.reset()
    
    def get_exc(self):
        with self.lock:
            return self._exc

    def get_rank(self):
        with self.lock:
            return self._rank

    def get_state(self):
        with self.lock:
            return self._state
    
    def can_put(self):
        with self.lock:
            #return self.inq.qsize() == 0
            return self._state == IDLE
        
    def put_input(self, unit):
        assert isinstance(unit, InputUnit)
        print "I am putting unit into inputq", unit.task_name, len(unit.input)
        with self.lock:
            self._rank += 1
            self.inq.put(unit)
        
    def get_input(self):
        with self.lock:
            if not self.inq.empty():
                self._state = PROCESSING
                return self.inq.get()
            return None
    
    def put_output(self, unit):
        assert isinstance(unit, OutputUnit)
        with self.lock:
            self.outq.put(unit)
            self._rank -= 1
            if self.inq.qsize() == 0:
                self._state = IDLE
    
    def get_outputs(self):
        ret = []
        while True:
            try:
                ret.append(self.outq.get_nowait())
            except qu.Empty:
                #print "queue empty exception is caught breaking out of the loop"
                break
        return ret

def test():
    pass
    from dexen.system.base import MyManager
    
    MyManager.register("SlaveComm", SlaveComm)
    mgr = MyManager()
    mgr.start()
    
    c = mgr.SlaveComm("SLAVE_TT", "")
    print c.get_exc()
    print c.can_put()


if __name__ == "__main__":
    test()
